package com.cu.employmentmanagementsystem.util;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.cu.employmentmanagementsystem.common.exception.ServiceException;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;


@Component
public class AESUtils
{

    private static final String KEY = "Ylyl199499??????";

    private static final HashMap<String, String> cache = new HashMap<>();

    private static final SymmetricCrypto AES = new SymmetricCrypto(SymmetricAlgorithm.AES, KEY.getBytes());


    public static String decryptString(String encryptHex)
    {
        if (cache.containsKey(encryptHex))
        {
            return cache.get(encryptHex);
        }
        String decryptedStr = AES.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
        cache.put(encryptHex, decryptedStr);
        return decryptedStr;
    }

    public static String encryptString(String encryptHex)
    {
        if (encryptHex == null)
        {
            return "";
        }
        String encryptedHex = AES.encryptHex(encryptHex);
        //缓存
        cache.put(encryptHex, encryptedHex);
        return encryptedHex;
    }

    public static <T> T decryptObject(T object)
    {
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields)
        {
            field.setAccessible(true);
            try
            {
                field.set(object, decryptString(field.get(object).toString()));
            }
            catch (IllegalAccessException e)
            {
                throw new ServiceException("解密对象失败");
            }
        }
        return object;
    }

    public static <T> T decryptObject(T object, String... fieldsName)
    {

        for (String fieldName : fieldsName)
        {
            Field field;
            try
            {
                field = object.getClass().getDeclaredField(fieldName);
            }
            catch (NoSuchFieldException e)
            {
                throw new ServiceException("解密对象失败:没有这个字段" + fieldName);
            }
            field.setAccessible(true);
            try
            {
                field.set(object, decryptString(field.get(object).toString()));
            }
            catch (IllegalAccessException e)
            {
                throw new ServiceException("解密对象失败");
            }
        }
        return object;
    }

    private static <T> T encryptField(T object, Field[] fields)
    {
        for (Field field : fields)
        {
            try
            {
                field.setAccessible(true);
                String fieldName = field.getName();
                Class<?> fieldType = field.getType();
                if (fieldType != String.class)
                {
                    continue;
                }
//                if ("serialVersionUID".equals(fieldName) || "id".equals(fieldName))
//                {
//                    continue;
//                }
                // 获取字段值
                Object dataField = field.get(object);
                // 字段值为空则跳过
                if (dataField == null)
                {
                    continue;
                }
                // 字段值不为空则加密
                String data = dataField.toString();
                if (StrUtil.isNotEmpty(data))
                {
                    field.set(object, encryptString(data));
                }
            }
            catch (IllegalAccessException e)
            {
                throw new ServiceException("加密对象失败");
            }
        }

        return object;
    }

    private static <T> T encryptField(T object, String... fieldNames)
    {
        Field[] fields = getFields(object);
        ArrayList<Field> fieldList = new ArrayList<>();
        for (String fieldName : fieldNames)
        {
            for (Field field : fields)
            {
                if (field.getName().equals(fieldName))
                {
                    fieldList.add(field);
                }
            }
        }

        Field[] encryptFields;
        encryptFields = fieldList.toArray(new Field[0]);
        return encryptField(object, encryptFields);
    }


    public static <T> T encryptObject(T object)
    {
        Field[] fields = object.getClass().getDeclaredFields();
        encryptField(object, fields);
        return object;
    }

    public static <T> T encryptObject(T object, String... fieldNames)
    {
        encryptField(object, fieldNames);
        return object;
    }

    public static <T> Field[] getFields(T object)
    {
        return object.getClass().getDeclaredFields();
    }


    public static void main(String[] args)
    {
        System.out.println(encryptString("" + 1000000.5024));
        System.out.println(decryptString("f99fa86105f30096e7948737762d4a82"));

    }
}
